import { streamRequest, extractJSON } from './LLMService'

export class QuizSolver {
  constructor(configs, onQuestionUpdate, logger) {
    this.configs = configs
    this.onQuestionUpdate = onQuestionUpdate
    this.logger = logger
    this.isRunning = false
    this.timeout = null
    this.currentQuestion = {
      type: '',
      text: '',
      answer: '',
      status: 'idle'
    }
  }

  updateConfigs(configs) {
    this.configs = { ...this.configs, ...configs }
    this.logger.log('配置已更新')
  }

  start() {
    this.isRunning = true
    this.processNextQuestion()
  }

  stop() {
    this.isRunning = false
    if (this.timeout) {
      clearTimeout(this.timeout)
      this.timeout = null
    }
    this.currentQuestion.status = 'idle'
    this.onQuestionUpdate(this.currentQuestion)
  }

  async processNextQuestion() {
    if (!this.isRunning) return

    try {
      await this.findAndSolveQuestion()
    } catch (error) {
      this.logger.error(`处理题目出错: ${error.message}`)
      this.currentQuestion.status = 'error'
      this.onQuestionUpdate(this.currentQuestion)
    }

    // 安排下一题处理
    if (this.isRunning) {
      this.timeout = setTimeout(() => this.processNextQuestion(), 2000)
    }
  }

  async findAndSolveQuestion() {
    // 获取题目类型和元素
    const selector = this.configs.appConfig?.selector || '[class^="questionTypeTitle___"]'
    const questionType = document.querySelector(selector)?.textContent?.trim().slice(2)
    const questionElement = document.querySelector('[class^="questionPart___"]')

    if (!questionElement) {
      this.logger.log('未找到题目')
      return
    }

    const questionText = questionElement.textContent.trim()
    
    // 更新当前问题
    this.currentQuestion = {
      type: questionType,
      text: questionText,
      answer: '',
      status: 'processing'
    }
    this.onQuestionUpdate(this.currentQuestion)
    
    this.logger.log(`正在处理${questionType}: ${questionText.substring(0, 30)}...`)

    // 根据题型处理
    switch (questionType) {
      case '填空题':
        await this.handleInputQuestion(questionText)
        break
      case '简答题':
        await this.handleShortAnswerQuestion(questionText)
        break
      case '单选题':
      case '多选题':
        await this.handleChoiceQuestion(questionText)
        break
      case '判断题':
        await this.handleTrueFalseQuestion(questionText)
        break
      case '编程题':
        this.logger.log('暂不支持编程题')
        break
      default:
        this.logger.log(`未知题型: ${questionType}`)
    }
  }

  async handleInputQuestion(text) {
    const answer = await this.fetchLLMAnswer(text)
    this.currentQuestion.answer = answer
    this.onQuestionUpdate(this.currentQuestion)
    
    // 从JSON提取答案
    const jsonString = extractJSON(answer)
    let answerList = []
    
    if (jsonString) {
      try {
        const parsed = JSON.parse(jsonString)
        answerList = Array.isArray(parsed.answer) ? parsed.answer : [parsed.answer]
      } catch (error) {
        this.logger.error(`解析JSON失败: ${error.message}`)
      }
    }
    
    // 填写输入框
    const inputs = document.querySelectorAll('[class*="fillInput___"]')
    
    for (let i = 0; i < answerList.length && i < inputs.length; i++) {
      this.setInputValue(inputs[i], answerList[i])
      await this.delay(500)
    }
    
    this.goToNextQuestion()
  }

  async handleShortAnswerQuestion(text) {
    const answer = await this.fetchLLMAnswer(text)
    this.currentQuestion.answer = answer
    this.onQuestionUpdate(this.currentQuestion)
    
    // 从JSON提取答案
    const jsonString = extractJSON(answer)
    let answerText = ''
    
    if (jsonString) {
      try {
        const parsed = JSON.parse(jsonString)
        const answerArray = Array.isArray(parsed.answer) ? parsed.answer : [parsed.answer]
        answerText = answerArray.join(' ')
      } catch (error) {
        this.logger.error(`解析JSON失败: ${error.message}`)
      }
    }
    
    // 查找文本框并填写
    const textarea = document.querySelector('textarea')
    if (textarea) {
      this.setInputValue(textarea, answerText)
    }
    
    this.goToNextQuestion()
  }

  async handleChoiceQuestion(text) {
    const answer = await this.fetchLLMAnswer(text)
    this.currentQuestion.answer = answer
    this.onQuestionUpdate(this.currentQuestion)
    
    // 从JSON提取答案
    const jsonString = extractJSON(answer)
    let answerList = []
    
    if (jsonString) {
      try {
        const parsed = JSON.parse(jsonString)
        answerList = Array.isArray(parsed.answer) ? parsed.answer : [parsed.answer]
      } catch (error) {
        this.logger.error(`解析JSON失败: ${error.message}`)
      }
    }
    
    // 点击选项
    for (const option of answerList) {
      const elements = document.querySelectorAll('[class^="answerWrap___"] label:not([class*="ant-checkbox-wrapper-checked"]) .font16')
      const match = this.findElementBySimilarText(option, 0.1, elements)
      
      if (match) {
        match.click()
        await this.delay(300)
      }
    }
    
    this.goToNextQuestion()
  }

  async handleTrueFalseQuestion(text) {
    const answer = await this.fetchLLMAnswer(text)
    this.currentQuestion.answer = answer
    this.onQuestionUpdate(this.currentQuestion)
    
    // 从JSON提取答案
    const jsonString = extractJSON(answer)
    let answerList = []
    
    if (jsonString) {
      try {
        const parsed = JSON.parse(jsonString)
        answerList = Array.isArray(parsed.answer) ? parsed.answer : [parsed.answer]
      } catch (error) {
        this.logger.error(`解析JSON失败: ${error.message}`)
      }
    }
    
    // 点击选项
    for (const option of answerList) {
      const elements = document.querySelectorAll('[class^="answerWrap___"] label')
      const match = this.findElementBySimilarText(option, 0.1, elements)
      
      if (match) {
        match.click()
        await this.delay(300)
      }
    }
    
    this.goToNextQuestion()
  }

  async fetchLLMAnswer(text) {
    // 使用新的LLMService
    let result = ''
    
    try {
      result = await streamRequest({
        text,
        config: this.configs,
        onContent: (content, fullText) => {
          // 实时更新答案
          this.currentQuestion.answer = fullText
          this.onQuestionUpdate(this.currentQuestion)
        },
        onError: (error) => {
          this.logger.error(`获取LLM答案出错: ${error.message}`)
        },
        onComplete: (finalText) => {
          this.logger.log(`LLM响应完成，长度: ${finalText.length}字符`)
        }
      })
      
      return result
    } catch (error) {
      this.logger.error(`获取LLM答案出错: ${error.message}`)
      return ''
    }
  }

  goToNextQuestion() {
    const nextBtn = [...document.querySelectorAll('span')].find(
      span => span.textContent.trim() === "下一题"
    )
    
    if (nextBtn) {
      nextBtn.click()
      this.currentQuestion.status = 'completed'
      this.onQuestionUpdate(this.currentQuestion)
    } else {
      this.logger.log('未找到"下一题"按钮')
    }
  }

  findElementBySimilarText(targetText, threshold = 0.8, elements) {
    let bestMatch = null
    let bestScore = 0

    for (const el of elements) {
      const text = el.textContent.trim()
      const score = this.similarity(text, targetText)
      if (score > bestScore && score >= threshold) {
        bestScore = score
        bestMatch = el
      }
    }

    return bestMatch
  }

  similarity(s1, s2) {
    if (!s1 || !s2) return 0
    s1 = s1.toLowerCase()
    s2 = s2.toLowerCase()
    const common = s1.split('').filter(c => s2.includes(c))
    return common.length / Math.max(s1.length, s2.length)
  }

  setInputValue(input, value) {
    try {
      // 使用原生输入设置器绕过React合成事件
      const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
        window.HTMLInputElement.prototype,
        "value"
      ).set
      
      nativeInputValueSetter.call(input, value)
      input.dispatchEvent(new Event('input', { bubbles: true }))
      input.dispatchEvent(new Event('focusout', { bubbles: true }))
    } catch (error) {
      this.logger.error(`设置输入值出错: ${error.message}`)
    }
  }

  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
  }
} 